package me.yricky.mayu.ui.fasta

import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.itemsIndexed
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.CatchingPokemon
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.center
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import me.yricky.mayu.ui.*
import me.yricky.mayu.ui.misc.svgFont
import kotlin.math.max
import kotlin.math.min

/**
 * @author Yricky
 * @date 2022/4/14
 */

@Composable
fun FastaSeqModel.DataContentItem(modifier: Modifier = Modifier){
    Column(modifier = modifier) {
        Row(Modifier.fillMaxWidth(),verticalAlignment = Alignment.CenterVertically){
            Icon(Icons.Rounded.CatchingPokemon,"",Modifier.size(32.dp))
            Text(name, fontSize = 16.sp, modifier = Modifier.padding(4.dp), maxLines = 1)
        }

        var gridHeight by remember { mutableStateOf(0.dp) }
        val dpAnim by animateDpAsState(gridHeight)
        Row {
            Text("长度：${seq.size}")
            Spacer(Modifier.size(8.dp))

            Text(if(gridHeight == 0.dp) "预览" else "收起", Modifier.clickable {
                gridHeight = if(gridHeight == 0.dp){
                    160.dp
                }else{
                    0.dp
                }
            }, textDecoration = TextDecoration.Underline, color = Color.Blue)
        }
        if(dpAnim> 0.dp){
            Column(Modifier.fillMaxWidth(1f).height(dpAnim).padding(8.dp)) {
                ParserSelector(Modifier.alpha(dpAnim.value/160))
                PreviewSequenceGrid()
            }
        }
    }
}



@Composable fun FastaSeqModel.PreviewSequenceGrid(modifier: Modifier = Modifier, append:@Composable (()->Unit)? = null){
    var location4 by remember { mutableStateOf(Location4(0x03)) }
    LazyVerticalGrid(
        GridCells.Adaptive(20.dp),
        modifier.pointerEvent(PointerEventType.Move){
            location4 = Location4.relative(it.changes.lastOrNull()?.position ?: Offset.Zero,size.center)
        }
    ) {
        itemsIndexed(seq) { index,item->
            SeqChar(
                Modifier.size(24.dp,36.dp).padding(1.dp,4.dp),
                seq = this@PreviewSequenceGrid,
                c = item,
                selected = false,
                popupLocation = location4,
                popupContent = defaultSeqCharPopup(index,this@PreviewSequenceGrid,item)
            )
        }
        append?.let{
            item { it() }
        }

    }
}


@OptIn(ExperimentalComposeUiApi::class)
@Composable fun FastaSeqModel.SequenceGrid(
    modifier: Modifier = Modifier,
    onSubSeqSelected:(IntRange)->Unit = {}
){
    var location4 by remember { mutableStateOf(Location4(0x03)) }
    var selectedStartIndex by remember { mutableStateOf(-1) }
    var selectedEndIndex by remember { mutableStateOf(-1) }
    val focusRequester by remember { mutableStateOf(FocusRequester()) }
    var popupContent:(@Composable ()->Unit)? by remember { mutableStateOf(null) }
    LazyVerticalGrid(
        GridCells.Adaptive(26.dp),
        modifier = modifier.pointLocation4{ location4 = it }
            .onKeyEvent {
                if(it.key.keyCode == Key.Escape.keyCode){
                    selectedStartIndex = -1
                    true
                }else false
            }.focusEnterExit(focusRequester),
    ) {
        itemsIndexed(
            seq,
            key = { i,c ->"$i$c" },
            contentType = { _,c -> c }
        ) { index,item->
            val selected by derivedStateOf {
                selectedStartIndex != -1 &&
                    (index in selectedStartIndex..selectedEndIndex ||
                            index in selectedEndIndex .. selectedStartIndex)
            }
            SeqChar(
                Modifier.pointerEvent(PointerEventType.Press){
                        if(it.buttons.isPrimaryPressed){
                            popupContent = defaultSeqCharPopup(index,this@SequenceGrid,item)
                            if(selectedStartIndex == -1){
                                selectedStartIndex = index
                                selectedEndIndex = index
                            }else{
                                onSubSeqSelected(IntRange(min(selectedEndIndex, selectedStartIndex),max(selectedEndIndex,selectedStartIndex)+1))
                                selectedStartIndex = -1
                            }
                        }else if(it.buttons.isSecondaryPressed){
                            selectedStartIndex = -1
                        }
                    }
                    .pointerEvent(PointerEventType.Enter){
                        if(selectedStartIndex != -1){
                            selectedEndIndex = index
                            val startIndex = min(selectedEndIndex, selectedStartIndex) + 1
                            val endIndex = max(selectedEndIndex,selectedStartIndex) + 1
                            popupContent = {
                                Text("($startIndex..$endIndex)长度为${endIndex- startIndex +1}的片段")
                            }
                        }else{
                            popupContent = defaultSeqCharPopup(index,this@SequenceGrid,item)
                        }
                    }.padding(1.dp,4.dp).size(24.dp,36.dp),
                seq = this@SequenceGrid,
                c = item,
                selected = selected,
                popupContent = popupContent,
                popupLocation = location4,
            )
        }
    }

}

@Composable
fun SeqChar(
    modifier: Modifier = Modifier,
    seq: FastaSeqModel? = null,
    c:Char,
    selected:Boolean = false,
    popupContent:@Composable (()->Unit)? = null,
    popupLocation: Location4 = Location4(0)
){
    var showPopup by remember { mutableStateOf(false) }
    Box(
        modifier
            .pointerEvent(PointerEventType.Enter){ showPopup = true }
            .pointerEvent(PointerEventType.Exit){ showPopup = false }
            .background(Color(seq?.parser?.colorOf(c) ?: 0)),
        contentAlignment = Alignment.Center
    ){
        Image(svgFont(c,selected),"$c")
        Popup(
            showPopup,
            popupLocation,
            content = popupContent
        )
    }

}

fun defaultSeqCharPopup(
    index:Int,
    seq: FastaSeqModel,
    c:Char
):@Composable ()->Unit = { Text("位点${index + 1}，${seq.parser.introOf(c)}") }